﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using FarseerPhysics.Collision;
using FarseerPhysics.Collision.Shapes;
using Somnus.Utils;
using Somnus.Core;
using FarseerPhysics.Dynamics.Contacts;

namespace Somnus.Objects
{
    class PhysicsObject
    {
        #region Variáveis Privadas
        
        /// <summary>
        /// Posição X do objeto
        /// </summary>
        private float _x = 0;

        /// <summary>
        /// Posição Y do objeto
        /// </summary>
        private float _y = 0;

        /// <summary>
        /// Tamanho da body do objeto
        /// </summary>
        private float _width;

        /// <summary>
        /// Tamanho da body do objeto
        /// </summary>
        private float _height;
        
        /// <summary>
        /// Fator de escala, pixel x metros
        /// </summary>
        private float _scaleFactor;

        private String _name;

        #endregion

        #region Variáveis Protegidas

        /// <summary>
        /// fixture da box
        /// </summary>
        protected Fixture _fixture;

        /// <summary>
        /// Shape da box
        /// </summary>
        protected PolygonShape _shape;

        #endregion

        #region Variáveis Publicas

        /// <summary>
        /// 
        /// </summary>
        public Body body;

        /// <summary>
        /// 
        /// </summary>
        public AnimatedObject art;

        /// <summary>
        /// Essa variável controla se art vai ou não ser scalonada para o tamanho da box
        /// </summary>
        public Boolean scaleArt;

        #endregion

        public PhysicsObject(DreamWorld world, String name, Texture2D texture, Nullable<Rectangle> sourceRectangle, float depth, Boolean isStatic, float x, float y, float width, float height, float rotation)
        {
            this._width = width;
            this._height = height;
            this._scaleFactor = world.ScaleFactor;
            this.scaleArt = true;
            this._name = name;

            //Criação do body
            body = new Body(world);
            body.IsStatic = isStatic;
            _shape = new PolygonShape(1);
            _shape.SetAsBox(width / 2 / _scaleFactor, height / 2 / _scaleFactor);
            _fixture = new Fixture(body, _shape);
            _fixture.Restitution = 0f;
            _fixture.Friction = 0.6f;
            _fixture.UserData = this;
            body.Position = new Vector2(x / _scaleFactor, y / _scaleFactor);
            body.Rotation = MathHelper.ToRadians(rotation);
            body.FixedRotation = true;
            body.Mass = 1;
            body.OnCollision += HandleBeginContact;
            body.OnSeparation += HandleEndContact;
        
            //Criação do art
            art = new AnimatedObject(texture, sourceRectangle, depth);

            world.addObject(this);
        }



        public virtual bool HandleBeginContact(Fixture thisFixture, Fixture otherFixture, Contact contact)
        {
            
            return true;
        }

        public virtual void HandleEndContact(Fixture thisFixture, Fixture otherFixture)
        {
        }



        public virtual void update(GameTime gameTime)
		{

            if (art != null)
            {
                art.x = body.Position.X * _scaleFactor;
                art.y = body.Position.Y * _scaleFactor;
                art.rotation = Rotation;

                if (scaleArt)
                {
                    art.Width = _width;
                    art.Height = _height;
                }
            }
		}

        public void draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            art.draw(gameTime, spriteBatch);
        }

        #region GETS & SETS

        public String Name
        {
            get
            {
                return _name;
            }
        }

        public float x
        {
            get
            {
                if (body != null)
                    return body.Position.X * _scaleFactor;
                else
                    return _x * _scaleFactor;
            }

            set
            {
                _x = value / _scaleFactor;

                if (body != null)
                {
                    Vector2 pos = body.Position;
                    pos.X = _x;
                    body.SetTransform(pos, body.Rotation);
                }
            }
        }

        public float y
        {
            get
            {
                if (body != null)
                    return body.Position.Y * _scaleFactor;
                else
                    return _y * _scaleFactor;
            }

            set
            {
                _y = value / _scaleFactor;

                if (body != null)
                {
                    Vector2 pos = body.Position;
                    pos.Y = _y;
                    body.SetTransform(pos, body.Rotation);
                }
            }
        }

        public float Rotation
        {
            get
            {
                
                return (float)MathHelper.ToDegrees(body.Rotation);
            }

            set
            {
                body.SetTransform(body.Position, MathHelper.ToRadians(value));
            }
        }

        #endregion




    }
}
